package com.syx.migration.service.impl;

import com.baomidou.dynamic.datasource.annotation.DSTransactional;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.syx.migration.IThread.MultiThread;
import com.syx.migration.domain.*;
import com.syx.migration.mapper.*;
import com.syx.migration.mapper.old.OldBkMapper;
import com.syx.migration.service.BkModuleService;
import com.syx.migration.service.MgnLinkIdService;
import com.syx.migration.utils.*;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;

import java.util.*;
import java.util.concurrent.atomic.AtomicInteger;

/**
 * @author Administrator
 * @date 2024/6/7 8:04
 * @description: 同步图书模块
 */
@RequiredArgsConstructor
@Service
public class BkModuleServiceImpl implements BkModuleService {

    private final SyxBookMapper bookMapper;
    private final SyxCheckMapper checkMapper;
    private final SyxBorrowMapper borrowMapper;
    private final SyxBracketMapper bracketMapper;
    private final SyxSubscribeMapper subscribeMapper;
    private final SyxCheckDetailMapper checkDetailMapper;
    private final SyxBookCatalogueMapper bookCatalogueMapper;

    private final MgnLinkIdService mgnLinkIdService;

    private final OldBkMapper oldBkMapper;

    private static final String BELONG = "aafde3efa746480ab7652b3be493dfc0";


    /**
     * 同步总括号
     */
    @DSTransactional
    @Override
    public void migrationBracket() {
        String tbName = "syx_bracket";
        // 预存征订号关联
        String subscribeTbName = "syx_bracket_subscribe";
        List<MgnLinkId> linkBracketIds = new ArrayList<>();
        List<MgnLinkId> linkBracketWithSubscribe = new ArrayList<>();
        List<SyxBracket> syxBrackets = BeanMapUtils.mapListToBeanList(oldBkMapper.getBracketList(BELONG), SyxBracket.class);
        syxBrackets.forEach(item ->{
            String newId = TimeIdWorker.createId(item.getCreateTime());
            String isEnable = item.getIsEnable();
            if (StringUtils.isBlank(isEnable) || isEnable.equals("true")){
                item.setIsEnable("0");
            }else {
                item.setIsEnable("1");
            }
            String registerTime = item.getRegisterTime();
            if (StringUtils.isBlank(registerTime)){
                registerTime += " 00:00:00";
            }
            item.setRegisterTime(registerTime);
            item.setId(Long.valueOf(newId));
            item.setTenantId(SchoolUtils.getTenantIdByBelong(item.getBelong()));
            linkBracketIds.add(new MgnLinkId(newId, item.getOldId(), tbName));
            linkBracketWithSubscribe.add(new MgnLinkId(newId, item.getOldSubscribeId(), subscribeTbName));
        });
        bracketMapper.insertBatch(syxBrackets);
        mgnLinkIdService.batchInsert(linkBracketIds);
        mgnLinkIdService.batchInsert(linkBracketWithSubscribe);
    }

    /**
     * 同步总括号
     */
    @DSTransactional
    @Override
    public void migrationBkCatalogue() {
        Long count = (Long) oldBkMapper.getBkCatalogueCount(BELONG).get(0).get("count");
        long startTime = System.currentTimeMillis();
        Integer size = 50000;
        int totalPage = Math.toIntExact(count / size) + 1;
        for (int i = 0; i < totalPage; i++) {
            int start = size * i;
            List<SyxBookCatalogue> syxBookCatalogues = BeanMapUtils.mapListToBeanList(
                    oldBkMapper.getBkCatalogueList(start, size, BELONG), SyxBookCatalogue.class);
            int idIndex = 0;
            List<MgnLinkId> linkIds = new ArrayList<>();
            for (SyxBookCatalogue item : syxBookCatalogues) {
                idIndex ++;
                String newId = TimeIdWorker.createId(item.getCreateTime(), idIndex);
                String tenantId = SchoolUtils.getTenantIdByBelong(item.getBelong());
                item.setTenantId(tenantId);
                if(StringUtils.isBlank(item.getIsTool()) || item.getIsTool().equals("否")){
                    item.setIsTool("1");
                }else {
                    item.setIsTool("0");
                }
                if (StringUtils.isNotBlank(item.getIsbn())){
                    item.setIsbn(item.getIsbn().replace("-", ""));
                }
                item.setId(Long.valueOf(newId));
                String callNumber = item.getCallNumber();
                String[] split = callNumber.split("/");
                String classifyNumber = split[0];
                item.setSingleBookName(item.getBookName());
                String titleNumber = "1";
                if (split.length > 1){
                    titleNumber = split[1];
                }
                if (StringUtils.isNotBlank(classifyNumber)){
                    String cnItemType = CnBookTypeUtils.getItemType(classifyNumber);
                    String cnTotalType = CnBookTypeUtils.item2Total(cnItemType);
                    item.setCnTotalType(cnTotalType);
                    item.setCnItemType(cnItemType);
                    item.setTitleNumber(titleNumber);
                    if (StringUtils.isNotBlank(titleNumber)){
                        if (titleNumber.contains(":")){
                            String[] split1 = titleNumber.split(":");
                            item.setTitleNumber(split1[0]);
                            item.setDiffNumber(split1[1]);
                        }
                    }
                    item.setClassifyNumber(classifyNumber);
                }
                linkIds.add(new MgnLinkId(newId, item.getOldId(), "syx_book_catalogue"));
            }
            bookCatalogueMapper.insertBatch(syxBookCatalogues);
            mgnLinkIdService.batchInsert(linkIds);
            System.out.println("第：" + i + "页，共：" + totalPage + "页");
        }
        System.out.printf("图书目录同步完成，耗时：%s%n", (System.currentTimeMillis() - startTime) / 1000);
    }

    /**
     * 同步图书
     */
    @DSTransactional
    @Override
    public void migrationBk() {
        long startTime = System.currentTimeMillis();
        System.out.println("开始时间：" + startTime);
        // 图书数量
        Long count = (Long) oldBkMapper.getBkCount(BELONG).get(0).get("count");
        // 总括号
        Map<String, String> bracketMap = mgnLinkIdService.getMapByTbName("syx_bracket");
        // 藏书室
        Map<String, String> libraryRoomMap = mgnLinkIdService.getMapByTbName("syx_library_room");
        // 书架
        Map<String, String> libraryBookselfMap = mgnLinkIdService.getMapByTbName("syx_library_bookself");
        Integer size = 200000;
        int totalPage = BaseUtils.divisionUp(Math.toIntExact(count), size);
        int idKey = 1111111;
        for (int i = 0; i < totalPage; i++) {
            int start = size * i + 1;
            if (start == 1){
                start = 0;
            }
            List<Map<String, Object>> bkMapList = oldBkMapper.getBkList(start, size, BELONG);
            int dbSize = bkMapList.size();
            int paramSize = 50000;
            int maxJ = BaseUtils.divisionUp(dbSize, paramSize);
            for (int j = 0; j < maxJ; j++) {
                int partStart = j * paramSize;
                int partEnd = (j + 1) * paramSize;
                partEnd = Math.min(partEnd, dbSize);
                List<Map<String, Object>> partMaps = bkMapList.subList(partStart, partEnd);
                this.bathSetParam(partMaps, idKey, bracketMap, libraryRoomMap, libraryBookselfMap);
                idKey += paramSize;
            }
            System.out.println("第：" + i + "页，共：" + totalPage + "页");
        }
        System.out.printf("图书同步完成，耗时：%s%n", (System.currentTimeMillis() - startTime) / 1000);
    }

    /**
     * 同步图书借阅记录
     */
    @DSTransactional
    @Override
    public void migrationBkBorrow() {
        // 读者
        Map<String, String> readerMap = mgnLinkIdService.getMapByTbName("syx_reader");
        List<Map<String, Object>> borrowMapList = oldBkMapper.getBorrowList(BELONG);
        List<MgnLinkId> linkIds = new ArrayList<>();
        List<SyxBorrow> borrowList = new ArrayList<>();
        AtomicInteger idKey = new AtomicInteger(11111);
        borrowMapList.forEach(map ->{
            idKey.getAndIncrement();
            SyxBorrow item = BeanMapUtils.mapToBean(map, SyxBorrow.class);
            String newId = TimeIdWorker.createId(item.getCreateTime(), idKey.get());
            String tenantId = SchoolUtils.getTenantIdByBelong(item.getBelong());
            item.setTenantId(tenantId);
            item.setId(Long.valueOf(newId));
            // 查找图书id
            Long bookId = this.getBookIdByTenantIdAndBookNum(tenantId, item.getOldBkNum());
            item.setBookId(bookId);
            String backStatus = item.getBackStatus();
            if (StringUtils.isBlank(backStatus) || backStatus.equals("借出")){
                item.setBackStatus("0");
            }else{
                item.setBackStatus("1");
            }
            String readerId = readerMap.get(item.getOldReaderId());
            if (Objects.isNull(readerId)){
                return;
            }
            item.setReaderId(Long.valueOf(readerId));
            linkIds.add(new MgnLinkId(newId, item.getOldId(), "syx_borrow"));
            borrowList.add(item);
        });
        borrowMapper.insertBatch(borrowList);
        mgnLinkIdService.batchInsert(linkIds);
    }

    /**
     * 同步图书预借记录
     */
    @DSTransactional
    @Override
    public void migrationBkSubscribe() {
        long startTime = System.currentTimeMillis();
        // 读者
        Map<String, String> readerMap = mgnLinkIdService.getMapByTbName("syx_reader");
        List<SyxSubscribe> subscribes = BeanMapUtils.mapListToBeanList(
                oldBkMapper.getSubscribeList(BELONG), SyxSubscribe.class);
        List<MgnLinkId> linkIds = new ArrayList<>();
        for (SyxSubscribe item : subscribes) {
            String newId = TimeIdWorker.createId(item.getCreateTime());
            String tenantId = SchoolUtils.getTenantIdByBelong(item.getBelong());
            item.setTenantId(tenantId);
            item.setId(Long.valueOf(newId));
            // 查找图书id
            Long bookId = this.getBookIdByTenantIdAndBookNum(tenantId, item.getOldBkNum());
            item.setBookId(bookId);
            String status = item.getStatus();
            if (StringUtils.isBlank(status) || status.equals("预约")){
                item.setStatus("0");
            }else if (status.equals("预约失效")){
                item.setStatus("2");
            }else{
                item.setStatus("1");
            }
            String readerId = readerMap.get(item.getOldReaderId());
            if (Objects.isNull(readerId)){
                continue;
            }
            item.setReaderId(Long.valueOf(readerId));
            linkIds.add(new MgnLinkId(newId, item.getOldId(), "syx_subscribe"));
        }
        subscribeMapper.insertBatch(subscribes);
        mgnLinkIdService.batchInsert(linkIds);
        System.out.printf("图书预借同步完成，耗时：%s%n", (System.currentTimeMillis() - startTime) / 1000);
    }

    /**
     * 根据租户id和图书编号获取图书id
     */
    private Long getBookIdByTenantIdAndBookNum(String belong, String bookNum){
        SyxBook book = bookMapper
                .selectOne(new LambdaQueryWrapper<SyxBook>()
                        .eq(SyxBook::getTenantId, belong).eq(SyxBook::getBookNumber, bookNum)
                        .last("limit 1"));
        if (Objects.isNull(book)){
            return -1L;
        }
        return book.getId();
    }

    /**
     * 多线程处理批量数据
     * @param splitList 处理数据
     * @return
     */
    public void bathSetParam(List<Map<String, Object>> splitList,
                                  Integer idKey,
                                  Map<String, String> bracketMap,
                                  Map<String, String> libraryRoomMap,
                                  Map<String, String> libraryBookselfMap) {
        try {
            MultiThread<Map<String, Object>, SyxBook> multiThread = new MultiThread<>(splitList) {
                final AtomicInteger idIndex = new AtomicInteger(idKey);
                @Override
                public SyxBook outExecute(int currentThread, Map<String, Object> data) {
                    SyxBook item = BeanMapUtils.mapToBean(data, SyxBook.class);
                    String newId = TimeIdWorker.createId(item.getCreateTime(), idIndex.incrementAndGet());
                    String tenantId = SchoolUtils.getTenantIdByBelong(item.getBelong());
                    item.setTenantId(tenantId);
                    item.setId(Long.valueOf(newId));
                    // 替换总括号
                    item.setBracketId(BaseUtils.str2Long(bracketMap.get(item.getOldBracketId())));
                    // 替换藏书室
                    item.setLibraryRoomId(BaseUtils.str2Long(libraryRoomMap.get(item.getOldLibraryId())));
                    // 替换书架
                    item.setLibraryBookselfId(BaseUtils.str2Long(libraryBookselfMap.get(item.getOldBookSelfId())));
                    // 替换编目
                    item.setCatalogueId(BaseUtils.str2Long(mgnLinkIdService.getNewIdByOldId("syx_book_catalogue", item.getOldCatalogId())));
                    // 替换书架
                    String bookselfFace = item.getBookselfFace();
                    if (StringUtils.isBlank(bookselfFace)){
                        item.setBookselfCol(null);
                        item.setBookselfTier(null);
                    }else {
                        bookselfFace = bookselfFace.equals("1") ? "A" : "B";
                        item.setBookselfFace(bookselfFace);
                    }
                    // CIRCULSTATE - 0在库、1预约、2在借
                    // status  - 0在库、1在借、2预约
                    String status = item.getStatus();
                    if (StringUtils.isBlank(status) || status.equals("0")){
                        item.setStatus("0");
                    }else if (status.equals("1")){
                        item.setStatus("2");
                    }else {
                        item.setStatus("1");
                    }
                    item.setCreateTime(DateTimeUtils.str2DateStr(item.getCreateTime()));
                    mgnLinkIdService.insert(newId, item.getOldId(), "syx_book");
                    return item;
                }
            };
            bookMapper.insertBatch(multiThread.getResult());
        } catch (Exception e) {
            e.printStackTrace();
            throw new RuntimeException("批量赋值异常");
        }
    }

    @Override
    @DSTransactional
    public void migrationCheck() {
        String tbName = "syx_check";
        ArrayList<MgnLinkId> mgnLinkIds = new ArrayList<>();
        List<SyxCheck> checkList = BeanMapUtils.mapListToBeanList(oldBkMapper.getCheckList(), SyxCheck.class);
        checkList.forEach(item -> {
            String newId = TimeIdWorker.createId(item.getCreateTime());
            item.setId(BaseUtils.str2Long(newId));
            String tenantId = SchoolUtils.getTenantIdByBelong(item.getBelong());
            item.setTenantId(tenantId);
            mgnLinkIds.add(new MgnLinkId(newId, item.getOldId(), tbName));
        });
        checkMapper.insertBatch(checkList);
        mgnLinkIdService.tbDelete(tbName);
        mgnLinkIdService.batchInsert(mgnLinkIds);
    }

    @Override
    @DSTransactional
    public void migrationCheckDetail() {
        String tbName = "syx_check_detail";
        long startTime = System.currentTimeMillis();
        System.out.println("开始时间：" + startTime);
        System.out.println("数据正在迁移中....");
        List<Map<String, Object>> checkDetailList = oldBkMapper.getCheckDetail();
        Map<String, String> bookMap = mgnLinkIdService.getMapByTbName("syx_book");
        Map<String, String> checkMap = mgnLinkIdService.getMapByTbName("syx_check");
        Map<String, String> readerMap = mgnLinkIdService.getMapByTbName("syx_reader");
        int size = 50000;
        int page = BaseUtils.divisionUp(Math.toIntExact(checkDetailList.size()), size);
        int key = 1111111;
        int count = 0;
        for (int i = 0; i < page; i++) {
            int start = i == 0 ? 0: size * i;
            int end = (i+1)*size;
            end = Math.min(end, checkDetailList.size());
            List<MgnLinkId> linkIds = new ArrayList<>();
            final AtomicInteger idIndex = new AtomicInteger(key);
            List<Map<String, Object>> checkDetailMaps = checkDetailList.subList(start, end);
            checkDetailMaps.forEach(item -> {
                String newId = TimeIdWorker.createId(item.get("createTime").toString(), idIndex.incrementAndGet());
                item.put("id", newId);
                linkIds.add(new MgnLinkId(newId, item.get("oldId").toString(), tbName));
                String tenantId = SchoolUtils.getTenantIdByBelong(item.get("belong").toString());
                item.put("tenantId", tenantId);
                if(Objects.nonNull(item.get("bookId"))){
                    String bookId = bookMap.get(item.get("bookId").toString());
                    item.put("bookId", bookId);
                }
                if(Objects.nonNull(item.get("checkId"))){
                    String checkId = checkMap.get(item.get("checkId").toString());
                    item.put("checkId", checkId);
                }
                if(Objects.nonNull(item.get("createBy"))){
                    String readerId = readerMap.get(item.get("createBy").toString());
                    item.put("createBy", readerId);
                }
            });
            List<SyxCheckDetail> checkDetailsList = BeanMapUtils.mapListToBeanList(checkDetailMaps, SyxCheckDetail.class);
            checkDetailMapper.insertBatch(checkDetailsList);
            mgnLinkIdService.batchInsert(linkIds);
            key += size;
            count += checkDetailsList.size();
            System.out.println("第：" + (i+1) + "页，共：" + page + "页");
        }
        System.out.printf("盘点详情同步完成，同步条数:"+ count +", 耗时: " + (System.currentTimeMillis() - startTime) / 1000);
    }
}
